package com.lagou.server;


import com.lagou.model.ExamReport;
import com.lagou.model.Question;
import com.lagou.model.User;
import com.lagou.model.UserMessage;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Random;

/**
 * 编辑器实现服务器主功能
 */
public class ServerView {
    /**
     * 合成复用原则
     */
    private ServerInitClose sic;
    private ServerDao sd;

    /**
     * 通过构造方法实现成员变量的初始化
     * @param sic
     */
    public ServerView(ServerInitClose sic, ServerDao sd) {
        this.sic = sic;
        this.sd = sd;
    }

    /**
     * 自定义成员方法实现客户端接收消息并处理
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public void serverReceive() throws IOException, ClassNotFoundException {
        while (true) {
            UserMessage um = (UserMessage) sic.getOis().readObject();
            System.out.println("接收到的消息是：" + um);

            switch (um.getType()) {
                case "managerCheck" : //验证管理员登陆
                    managerCheck(um);
                    break;
                case "userCheck" :   //验证用户登陆
                    userCheck(um);
                    break;
                case "addStudent" :   //添加用户
                    addStudent(um);
                    break;
                case "deleteStudent" :  //删除用户
                    deleteStudent(um);
                    break;
                case "updateStudent" :   //修改用户
                    updateStudent(um);
                    break;
                case "searchStudent" :  //查找用户
                    searchStudent(um);
                    break;
                case "findAllStudent" :  //遍历用户
                    findAllStudent();
                    break;
                case "addQuestion" :   //添加考题
                    addQuestion(um);
                    break;
                case "deleteQuestion" :   //删除考题
                    deleteQuestion(um);
                    break;
                case "updateQuestion" :   //修改考题
                    updateQuestion(um);
                    break;
                case "searchQuestion" :  //查找考题
                    searchQuestion();
                    break;
                case "loadQuestion" :  //导入考题
                    loadQuestion(um);
                    break;
                case "startTest" :    //开始考试
                    startTest();
                    break;
                case "saveExamReport" :  //查看和导出成绩单
                    saveExamReport();
                    break;
                case "updatePassword" :  //修改密码
                    updatePassword(um);
                    break;
                case "clientOut" :        //清空当前用户的信息
                    sd.clearCurrentUser();
                    break;
                case "clientExit" :      //客户端下线
                    System.out.println("客户端已下线");;
                    return;
                default:
                    System.out.println("您的输入有误!");
            }
            System.out.println("当前用户为：" + sd.getCurrentUser());
            System.out.println();
        }
    }

    /**
     * 实现修改密码
     * @param um
     * @throws IOException
     */
    private void updatePassword(UserMessage um) throws IOException {
        //调用修改密码的方法
        if (sd.serverUpdatePassword(um.getUser().getPassword())) {
            um.setType("success");
            System.out.println("密码修改成功");
        } else {
            um.setType("fail");
            System.out.println("密码修改失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 导出成绩单
     * @throws IOException
     */
    private void saveExamReport() throws IOException {
        //从数据库读取成绩单
        ExamReport examReport = sd.getExamReportToDataBase();
        if (null != examReport) {
            System.out.println("获取成功");
        }else {
            System.out.println("获取失败");
        }

        //发送考试报告
        sic.getOos().writeObject(examReport);
    }

    /**
     * 实现开始考试功能
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void startTest() throws IOException, ClassNotFoundException {
        //检查数据是否存在
        if (sd.getQuestions() == null || sd.getQuestions().size() < 3) {
            System.out.println("题库暂无数据，或考题数不足");
            sic.getOos().writeObject(null);
            return;
        }

        Random random = new Random();
        //随机获取三道考题
        int size = sd.getQuestions().size();
        int i = random.nextInt(size);
        int k = random.nextInt(size);
        int j = random.nextInt(size);
        if (i == j) {j = (j + 1) % size;}
        if (k == i) {k = (k + 1) % size;}
        if (k == j) {k = (k + 1) % size;}
        String[] questions = new String[3];
        questions[0] = sd.getQuestions().get(i).getQuestion();
        questions[1] = sd.getQuestions().get(j).getQuestion();
        questions[2] = sd.getQuestions().get(k).getQuestion();

        //将考题发给客户端
        sic.getOos().writeObject(questions);

        //读取客户端的答案
        String[] answer = (String[]) sic.getOis().readObject();

        //和正确答案对比
        int num = 0;
        if (sd.getQuestions().get(i).getAnswer().equalsIgnoreCase(answer[0])){num++;}
        if (sd.getQuestions().get(j).getAnswer().equalsIgnoreCase(answer[1])){num++;}
        if (sd.getQuestions().get(k).getAnswer().equalsIgnoreCase(answer[2])){num++;}

        //生成考试成绩单
        ExamReport examReport = new ExamReport();
        examReport.setUsername(sd.getCurrentUser().getUserName());
        examReport.setGrade(num);
        Question[] q = new Question[3];
        examReport.setAnswer(answer);
        q[0] = sd.getQuestions().get(i);
        q[1] = sd.getQuestions().get(j);
        q[2] = sd.getQuestions().get(k);
        examReport.setQuestions(q);

        System.out.println(examReport);

        //成绩单保存到数据库
        sd.saveExamReportToDataBase(examReport);
    }

    /**
     *实现考题导入
     * @param um
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void loadQuestion(UserMessage um) throws IOException, ClassNotFoundException {
        LinkedList<Question> questions = (LinkedList<Question>) sic.getOis().readObject();

        //调用遍历考题的方法
        if (sd.serverLoadQuestion(questions)) {
            um.setType("success");
            System.out.println("导入考题成功");
        } else {
            um.setType("fail");
            System.out.println("导入考题失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 实现查找考题
     * @param
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void searchQuestion() throws IOException, ClassNotFoundException {
        String str = (String) sic.getOis().readObject();

        //调用查找考题的方法
        Question question = sd.serverSearchQuestion(str);
        if (null != question) {
            System.out.println("考题查找成功");
            sic.getOos().writeObject(new Question(question.getQuestion(),question.getAnswer()));
        } else {
            System.out.println("考题查找失败");
            sic.getOos().writeObject(null);
        }
        System.out.println("服务器已发送考题查找结果");
    }

    /**
     * 实现修改考题
     * @param um
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void updateQuestion(UserMessage um) throws IOException, ClassNotFoundException {
        //从客户端读取信息
        String question = (String) sic.getOis().readObject();
        String options = (String) sic.getOis().readObject();
        String answer = (String) sic.getOis().readObject();

        //调用修改考题的方法
        if (sd.serverUpdateQuestion(question, options, answer)) {
            um.setType("success");
            System.out.println("考题修改成功");
        } else {
            um.setType("fail");
            System.out.println("考题修改失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 实现删除考题
     * @param um
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void deleteQuestion(UserMessage um) throws IOException, ClassNotFoundException {
        String str = (String) sic.getOis().readObject();

        //调用删除考题的方法
        if (sd.serverDeleteQuestion(str)) {
            um.setType("success");
            System.out.println("考题删除成功");
        } else {
            um.setType("fail");
            System.out.println("考题删除失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 实现添加考题
     * @param um
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void addQuestion(UserMessage um) throws IOException, ClassNotFoundException {
        Question question = (Question) sic.getOis().readObject();

        //调用增加考题的方法
        if (sd.serverAddQuestion(question)) {
            um.setType("success");
            System.out.println("考题添加成功");
        } else {
            um.setType("fail");
            System.out.println("考题添加失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 遍历学员信息
     * @throws IOException
     */
    private void findAllStudent() throws IOException {
        LinkedList<User> users = new LinkedList<>(sd.getUserList());
        //users.addAll(sd.getUserList());
        
        //查到的对象发送给客户端
        sic.getOos().writeObject(users);
    }

    /**
     * 查找学员信息
     * @param um
     * @throws IOException
     */
    private void searchStudent(UserMessage um) throws IOException {
        //调用查找方法
        User user = sd.serverSearchStudent(um.getUser());
        if (null != user) {
            um.setType("success");
            um.setUser(user);
            System.out.println("查询成功" + user);
        } else {
            um.setType("fail");
            System.out.println("查询失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 更新学员信息
     * @param um
     * @throws IOException
     */
    private void updateStudent(UserMessage um) throws IOException {
        //调用更新方法
        if (sd.serverUpdateStudent(um.getUser())) {
            um.setType("success");
            System.out.println("更新成功");
        } else {
            um.setType("fail");
            System.out.println("更新失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 删除学员信息
     * @param um
     * @throws IOException
     */
    private void deleteStudent(UserMessage um) throws IOException {
        //调用删除方法
        if (sd.serverDeleteStudent(um.getUser())) {
            um.setType("success");
            System.out.println("删除成功");
        } else {
            um.setType("fail");
            System.out.println("删除失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 实现学员账户的登陆
     * @param um
     * @throws IOException
     */
    private void userCheck(UserMessage um) throws IOException {
        //调用方法实现管理员账号密码的校验
        if (sd.serverUserCheck(um.getUser())) {
            um.setType("success");
            System.out.println("校验成功");
        } else {
            um.setType("fail");
            System.out.println("校验失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 添加学员信息
     * @param um
     * @throws IOException
     */
    private void addStudent(UserMessage um) throws IOException {
        if (sd.serverAddStudent(um.getUser())) {
            um.setType("success");
            System.out.println("添加成功");
        } else {
            um.setType("fail");
            System.out.println("添加失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 实现管理员账户信息的较验功能
     * @param um
     * @throws IOException
     */
    private void managerCheck(UserMessage um) throws IOException {
        //调用方法实现管理员账号密码的校验
        if (sd.serverManageCheck(um.getUser())) {
            um.setType("success");
            System.out.println("校验成功");
        } else {
            um.setType("fail");
            System.out.println("校验失败");
        }
        //将得到的标识返回给客户端
        sic.getOos().writeObject(um);
    }

    /**
     * 调用读取学员信息的方法
     */
    public void loadAllFromDataBase() {
        //导入数据库中的学员信息
        sd.loadUserFromDataBase();
        //导入数据库中考题
        sd.loadQuestionsFromDataBase();
    }

    /**
     * 调用保存学员信息的方法
     */
    public void saveAllToDataBase() {
        //保存学员信息到数据库
        sd.saveUserToDataBase();
        //保存考题到数据库
        sd.saveQuestionsToDataBase();
    }
}
